package leetcode.dfs;

/**
 * 给你一个 m x n 的二进制矩阵 mat。
 *
 * 每一步，你可以选择一个单元格并将它反转（反转表示 0 变 1 ，1 变 0 ）。如果存在和它相邻的单元格，那么这些相邻的单元格也会被反转。（注：相邻的两个单元格共享同一条边。）
 *
 * 请你返回将矩阵 mat 转化为全零矩阵的最少反转次数，如果无法转化为全零矩阵，请返回 -1 。
 *
 * 二进制矩阵的每一个格子要么是 0 要么是 1 。
 *
 * 全零矩阵是所有格子都为 0 的矩阵。
 *
 *  
 *
 * 示例 1：
 *
 *
 *
 * 输入：mat = [[0,0],[0,1]]
 * 输出：3
 * 解释：一个可能的解是反转 (1, 0)，然后 (0, 1) ，最后是 (1, 1) 。
 * 示例 2：
 *
 * 输入：mat = [[0]]
 * 输出：0
 * 解释：给出的矩阵是全零矩阵，所以你不需要改变它。
 * 示例 3：
 *
 * 输入：mat = [[1,1,1],[1,0,1],[0,0,0]]
 * 输出：6
 * 示例 4：
 *
 * 输入：mat = [[1,0,0],[1,0,0]]
 * 输出：-1
 * 解释：该矩阵无法转变成全零矩阵
 *  
 *
 * 提示：
 *
 * m == mat.length
 * n == mat[0].length
 * 1 <= m <= 3
 * 1 <= n <= 3
 * mat[i][j] 是 0 或 1 。
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix
 */

public class 转化为全零矩阵的最少反转次数 {

    private static int min;
    private static final int[] dirs = new int[]{-1,0,1,0,-1};


    // 可将矩阵视为一个一维数组 通过y = pos/n 和 x = pos%n 确定坐标
    public static int minFlips(int[][] mat) {
        int n = mat.length;
        int m = mat[0].length;
        min = Integer.MAX_VALUE;
        dfs(mat, n, m, 0, 0);
        if (min == Integer.MAX_VALUE) return -1;
        return min;
    }

    private static void dfs(int[][] mat, int n, int m, int pos, int step){
        if (step < min && pos <= n*m){
            if (isZero(mat)){
                min = step;
            }else {
                if (pos < n*m){
                    int x = pos % m;
                    int y = pos / m;
                    dfs(mat, n, m, pos+1, step);
                    reversal(mat, n, m, x, y);
                    dfs(mat, n, m, pos+1, step+1);
                    reversal(mat, n, m, x, y);
                }
            }
        }
    }

    private static boolean isZero(int[][] mat){
        for (int[] i : mat){
            for (int j : i){
                if (j != 0) return false;
            }
        }
        return true;
    }

    private static void reversal(int[][] mat, int n, int m, int x, int y){
        mat[y][x] = mat[y][x] == 1 ? 0 : 1;
        for (int i = 0; i < dirs.length-1; i++){
            if (x+dirs[i]<m && y+dirs[i+1]<n && x+dirs[i]>=0 && y+dirs[i+1]>=0){
                mat[y+dirs[i+1]][x+dirs[i]] = mat[y+dirs[i+1]][x+dirs[i]]==1 ? 0 : 1;
            }
        }
    }

    public static void main(String[] args){
        int[][] a = new int[][]{{1,0,0},{1,0,0},{0,0,0}};
        System.out.println(minFlips(a));
    }
}
